package net.zoneland.greenleaf.log.aop;

import java.lang.reflect.Field;
import java.util.Date;

import net.zoneland.greenleaf.common.date.DateOperation;
import net.zoneland.greenleaf.log.entity.Log_method_call;
import net.zoneland.greenleaf.log.service.Log_method_callServiceI;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;


/**
 * 记录方法的执行时间
 * @author liyi
 */
public class ControllerMethodTimeAdviceService implements MethodInterceptor {
	
	public static Logger logger=Logger.getLogger(ControllerMethodTimeAdviceService.class);
	
	private DateOperation dateOperation = new DateOperation();
	
	private Log_method_callServiceI method_callService;  
	
    public Log_method_callServiceI getMethod_callService() {
		return method_callService;
	}	
    
	public void setMethod_callService(Log_method_callServiceI method_callService) {
		this.method_callService = method_callService;
	}

	/**
     * 拦截要执行的目标方法
     * 1、先获取到拦截的类的对象
     * 2、获取类的monitor属性值，如果是true为需要监控，如果为false则不需要监控
     * 3、获取业务逻辑执行前后的时间
     * 4、将业务逻辑执行的时间记录到数据库中
     */
    public Object invoke(MethodInvocation invocation) throws Throwable {
    	Class<?> _class = invocation.getMethod().getDeclaringClass();
    	Field field = null; 
    	Object result = null;
    	boolean monitor = false;
    	
    	try{
    		if(_class!=null){
    			field = _class.getDeclaredField("monitor");
    		}else{
    			logger.error("未获取到Controller类对象。");
    		}
    	}catch(Exception e){
    		logger.error("获取Controller类对象的monitor属性出错。", e);
    	}
    	
    	if(field!=null){
    		monitor = field.getBoolean(_class.newInstance());
    	}
    	
    	if(monitor){
    		Date method_start_time = new Date();
        	
        	//让Controller执行业务逻辑，执行完成后再记录时间
            result = invocation.proceed();
            
            Date method_end_time = new Date();
            
        	//方法参数类型，转换成简单类型
        	Class[] params = invocation.getMethod().getParameterTypes();
        	
        	String[] simpleParams = new String[params.length];
        	
        	for (int i = 0; i < params.length; i++) {
    			simpleParams[i] = params[i].getSimpleName();
    		}
        	
        	//如果此类需要监控性能，则进行执行时间记录
        	try{
	    		addMethodCall(method_start_time, method_end_time, invocation.getThis().getClass().getName() + "." + invocation.getMethod().getName() + "("+StringUtils.join(simpleParams,",")+")] " );			
			}catch(Exception e){
				logger.error( invocation.getThis().getClass().getName() + "." + new Throwable().getStackTrace()[0].getMethodName()+"方法调用日志记录失败，请联系管理员。信息：", e);
			}
        	
    	}else{
    		
    		result = invocation.proceed();
    		
    	}
    	
        return result;
    }
    
    /**
     * 向数据库记录业务逻辑执行时间的方法 
     * @param method_start_time
     * @param method_end_time
     * @param methodName
     */
    public void addMethodCall(Date method_start_time, Date method_end_time, String methodName) {
		Log_method_call method_call = new Log_method_call();
		
		try {
			method_call.setCall_endtime(dateOperation.getDateFromDate(method_end_time, "yyyy-MM-dd HH:mm:ss"));
		} catch (Exception e) {
			logger.error( "日期格式转换异常", e);
		}
		
		try {
			method_call.setCall_starttime(dateOperation.getDateFromDate(method_start_time, "yyyy-MM-dd HH:mm:ss"));
		} catch (Exception e) {
			logger.error( "日期格式转换异常", e);
		}
		
		try {
			method_call.setMethod_name(methodName);
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		
		try {
			method_call.setThread_id(Thread.currentThread().getId()+"");
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		
		try {
			method_call.setThread_name(Thread.currentThread().getName());
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		
		try {
			method_call.setCall_continued(method_end_time.getTime() - method_start_time.getTime());
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		try {
			method_call.setMethod_call_year(Integer.parseInt(dateOperation.getYear(method_start_time)));
		} catch (Exception e) {
			logger.error( "日期格式转换异常", e);
		}
		
		try {
			method_call.setMethod_call_month(method_start_time.getMonth()+1);
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		
		try {
			method_call.setMethod_call_day(method_start_time.getDate());
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		try {
			method_call.setMethod_call_hour(method_start_time.getHours());
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		
		try {
			method_call.setMethod_call_mins(method_start_time.getMinutes());
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		
		try {
			method_call.setMethod_call_secs(method_start_time.getSeconds());
		} catch (Exception e) {
			logger.error( "数据格式转换异常", e);
		}
		
		method_callService.add(method_call);
	}
}
